﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using System.Collections;

namespace ProceduralGolf
{
    class ClubManager
    {
        private SpriteFont font;
        private Game game;
        int clubIndex = 0;
        SpriteBatch spriteBatch;

        Random rand = new Random();

        public Vector2 Position { get; set; }

        public ClubManager(Game game)
        {
            this.game = game;
            font = game.Content.Load<SpriteFont>("MyFont");
            spriteBatch = new SpriteBatch(game.GraphicsDevice);
        }

        private float property(GolfClub club, GolfCourseLayout.GolfCourseLayer layer)
        {
            switch (layer)
            {
                case GolfCourseLayout.GolfCourseLayer.GREEN:
                    if (club.Name.ToLower().EndsWith("driver"))
                        return 0.75f;
                    if (club.Name.ToLower().EndsWith("wood"))
                        return 1f;
                    if (club.Name.ToLower().EndsWith("iron"))
                        return 1f;
                    if (club.Name.ToLower().EndsWith("pw"))
                        return 1f;
                    if (club.Name.ToLower().EndsWith("sw"))
                        return 1f;
                    return 1.0f; //unknown; should not happen
                case GolfCourseLayout.GolfCourseLayer.FAIRWAY:
                    if(club.Name.ToLower().EndsWith("driver"))
                        return 0.75f;
                    if (club.Name.ToLower().EndsWith("wood"))
                        return 0.99f;
                    if (club.Name.ToLower().EndsWith("iron"))
                        return 0.99f;
                    if (club.Name.ToLower().EndsWith("pw"))
                        return 0.95f;
                    if (club.Name.ToLower().EndsWith("sw"))
                        return 0.9f;
                    return 1.0f; //unknown; should not happen
                case GolfCourseLayout.GolfCourseLayer.FRINGE:
                    if (club.Name.ToLower().EndsWith("driver"))
                        return 0.5f;
                    if (club.Name.ToLower().EndsWith("wood"))
                        return 0.7f;
                    if (club.Name.ToLower().EndsWith("iron"))
                        return 0.85f;
                    if (club.Name.ToLower().EndsWith("pw"))
                        return 0.85f;
                    if (club.Name.ToLower().EndsWith("sw"))
                        return 0.85f;
                    return 1.0f; //unknown; should not happen
                case GolfCourseLayout.GolfCourseLayer.HAZARDS:
                    if (club.Name.ToLower().EndsWith("driver"))
                        return 0.125f;
                    if (club.Name.ToLower().EndsWith("wood"))
                        return 0.25f;
                    if (club.Name.ToLower().EndsWith("iron"))
                        return 0.25f;
                    if (club.Name.ToLower().EndsWith("pw"))
                        return 0.25f;
                    if (club.Name.ToLower().EndsWith("sw"))
                        return 0.9f;
                    return 1.0f; //unknown; should not happen
                case GolfCourseLayout.GolfCourseLayer.ROUGH:
                    if (club.Name.ToLower().EndsWith("driver"))
                        return 0.25f;
                    if (club.Name.ToLower().EndsWith("wood"))
                        return 0.5f;
                    if (club.Name.ToLower().EndsWith("iron"))
                        return 0.75f;
                    if (club.Name.ToLower().EndsWith("pw"))
                        return 0.75f;
                    if (club.Name.ToLower().EndsWith("sw"))
                        return 0.75f;
                    return 1.0f; //unknown; should not happen
                default:
                    return 0.0f;
            }
        }

        public void nextClub()
        {
            clubIndex = ++clubIndex % GolfClub.Clubs.Length;
        }

        public void prevClub()
        {
            --clubIndex;
            if (clubIndex < 0) clubIndex = GolfClub.Clubs.Length - 1;
        }

        public GolfClub Club { get { return GolfClub.Clubs[clubIndex]; } }

        public void Draw()
        {
            Vector2 offset = font.MeasureString(Club.Name) / 2;
            spriteBatch.Begin();
            
            spriteBatch.DrawString(font, Club.Name, Position - offset, Color.White);
            spriteBatch.End();
        }

        private float calculatePowerDev(GolfClub club, GolfCourseLayout.GolfCourseLayer layer, float power)
        {
            return property(club, layer) * power;
        }

        private float calculateYawDev(GolfClub club, GolfCourseLayout.GolfCourseLayer layer, float yaw)
        {
            float devProperty = 1.0f - property(club, layer);
            float maxDev = MathHelper.Pi / 8.0f;
            float dev = devProperty * maxDev;

            float minAngle = yaw - dev;
            float maxAngle = yaw + dev;

            return MathHelper.Lerp(minAngle, maxAngle, (float)rand.NextDouble());
        }

        public Vector3 hit(float yaw, float power, GolfCourseLayout.GolfCourseLayer layer, bool tee)
        {
            float devYaw = calculateYawDev(Club, layer, yaw);
            float devPower = calculatePowerDev(Club, layer, power);
            
            //special case for first hit
            if (tee)
            {
                devYaw = yaw;
                devPower = power;   
            }

            //Console.WriteLine("power: " + power);
            //Console.WriteLine("dev power: " + devPower);
            //Console.WriteLine("yaw: " + yaw);
            //Console.WriteLine("devYaw: " + devYaw);

            return Club.hit(devYaw, devPower);
        }

    }
}
